---
title: 'Assertions in Cypress: A Guide'
description: 'Assertions available in Cypress with Chai, Chai-jQuery, and Sinon-Chai assertions'
sidebar_label: 'Assertions'
---

<ProductHeading product="app" />

# Assertions

:::info

##### <Icon name="question-circle" color="#4BBFD2" /> What you'll learn

- Assertions available in Cypress with Chai, Chai-jQuery, and Sinon-Chai assertions
- How to write assertions for common use cases
- How to chain assertions together

:::

Cypress bundles the popular [Chai](/app/references/assertions#Chai) assertion
library, as well as helpful extensions for
[Sinon](/app/references/assertions#Sinon-Chai) and
[jQuery](/app/references/assertions#Chai-jQuery), bringing you dozens of
powerful assertions for free.

:::tip

If you're looking to understand **how** to use these assertions please read
about assertions in our
[Introduction to Cypress](/app/core-concepts/introduction-to-cypress#Assertions)
guide.

:::

## Chai

<Icon name="github" url="https://github.com/chaijs/chai" />

These chainers are available for BDD assertions (`expect`/`should`). Aliases
listed can be used interchangeably with their original chainer. You can see the
entire list of available BDD Chai assertions [here](http://chaijs.com/api/bdd/).

| Chainer                                                                                   | Example                                                                                                                                                                                                                |
| ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| not                                                                                       | `.should('not.equal', 'Jane')`<br />`expect(name).to.not.equal('Jane')`                                                                                                                                                |
| deep                                                                                      | `.should('deep.equal', { name: 'Jane' })`<br />`expect(obj).to.deep.equal({ name: 'Jane' })`                                                                                                                           |
| nested                                                                                    | `.should('have.nested.property', 'a.b[1]')`<br />`.should('nested.include', {'a.b[1]': 'y'})`<br />`expect({a: {b: 'x'}}).to.have.nested.property('a.b')`<br />`expect({a: {b: 'x'}}).to.nested.include({'a.b': 'x'})` |
| ordered                                                                                   | `.should('have.ordered.members', [1, 2])`<br />`expect([1, 2]).to.have.ordered.members([1, 2])`<br />`expect([1, 2]).not.to.have.ordered.members([2, 1])`                                                              |
| any                                                                                       | `.should('have.any.keys', 'age')`<br />`expect(arr).to.have.any.keys('age')`                                                                                                                                           |
| all                                                                                       | `.should('have.all.keys', 'name', 'age')`<br />`expect(arr).to.have.all.keys('name', 'age')`                                                                                                                           |
| a(_type_) <br /><small>**Aliases:** an</small>                                            | `.should('be.a', 'string')`<br />`expect('test').to.be.a('string')`                                                                                                                                                    |
| include(_value_) <br /><small>**Aliases:** contain, includes, contains</small>            | `.should('include', 2)`<br />`expect([1,2,3]).to.include(2)`                                                                                                                                                           |
| ok                                                                                        | `.should('not.be.ok')`<br />`expect(undefined).to.not.be.ok`                                                                                                                                                           |
| true                                                                                      | `.should('be.true')`<br />`expect(true).to.be.true`                                                                                                                                                                    |
| false                                                                                     | `.should('be.false')`<br />`expect(false).to.be.false`                                                                                                                                                                 |
| null                                                                                      | `.should('be.null')`<br />`expect(null).to.be.null`                                                                                                                                                                    |
| undefined                                                                                 | `.should('be.undefined')`<br />`expect(undefined).to.be.undefined`                                                                                                                                                     |
| exist                                                                                     | `.should('exist')`<br />`expect(myVar).to.exist`                                                                                                                                                                       |
| empty                                                                                     | `.should('be.empty')`<br />`expect([]).to.be.empty`                                                                                                                                                                    |
| arguments <br /><small>**Aliases:** Arguments</small>                                     | `.should('be.arguments')`<br />`expect(arguments).to.be.arguments`                                                                                                                                                     |
| equal(_value_) <br /><small>**Aliases:** equals, eq</small>                               | `.should('equal', 42)`<br />`expect(42).to.equal(42)`                                                                                                                                                                  |
| deep.equal(_value_)                                                                       | `.should('deep.equal', { name: 'Jane' })`<br />`expect({ name: 'Jane' }).to.deep.equal({ name: 'Jane' })`                                                                                                              |
| eql(_value_) <br /><small>**Aliases:** eqls</small>                                       | `.should('eql', { name: 'Jane' })`<br />`expect({ name: 'Jane' }).to.eql({ name: 'Jane' })`                                                                                                                            |
| greaterThan(_value_) <br /><small>**Aliases:** gt, above</small>                          | `.should('be.greaterThan', 5)`<br />`expect(10).to.be.greaterThan(5)`                                                                                                                                                  |
| least(_value_)<br /><small>**Aliases:** gte</small>                                       | `.should('be.at.least', 10)`<br />`expect(10).to.be.at.least(10)`                                                                                                                                                      |
| lessThan(_value_) <br /><small>**Aliases:** lt, below</small>                             | `.should('be.lessThan', 10)`<br />`expect(5).to.be.lessThan(10)`                                                                                                                                                       |
| most(_value_) <br /><small>**Aliases:** lte</small>                                       | `.should('have.length.of.at.most', 4)`<br />`expect('test').to.have.length.of.at.most(4)`                                                                                                                              |
| within(_start_, _finish_)                                                                 | `.should('be.within', 5, 10)`<br />`expect(7).to.be.within(5, 10)`                                                                                                                                                     |
| instanceOf(_constructor_) <br /><small>**Aliases:** instanceof</small>                    | `.should('be.instanceOf', Array)`<br />`expect([1, 2, 3]).to.be.instanceOf(Array)`                                                                                                                                     |
| property(_name_, _[value]_)                                                               | `.should('have.property', 'name')`<br />`expect(obj).to.have.property('name')`                                                                                                                                         |
| deep.property(_name_, _[value]_)                                                          | `.should('have.deep.property', 'tests[1]', 'e2e')`<br />`expect(deepObj).to.have.deep.property('tests[1]', 'e2e')`                                                                                                     |
| ownProperty(_name_) <br /><small>**Aliases:** haveOwnProperty, own.property</small>       | `.should('have.ownProperty', 'length')`<br />`expect('test').to.have.ownProperty('length')`                                                                                                                            |
| ownPropertyDescriptor(_name_) <br /><small>**Aliases:** haveOwnPropertyDescriptor</small> | `.should('have.ownPropertyDescriptor', 'a')`<br />`expect({a: 1}).to.have.ownPropertyDescriptor('a')`                                                                                                                  |
| lengthOf(_value_)                                                                         | `.should('have.lengthOf', 4)`<br />`expect('test').to.have.lengthOf(4)`                                                                                                                                                |
| match(_RegExp_) <br /><small>**Aliases:** matches</small>                                 | `.should('to.match', /^test/)`<br />`expect('testing').to.match(/^test/)`                                                                                                                                              |
| string(_string_)                                                                          | `.should('have.string', 'test')`<br />`expect('testing').to.have.string('test')`                                                                                                                                       |
| keys(_key1_, _[key2]_, _[...]_) <br /><small>**Aliases:** key</small>                     | `.should('have.keys', 'pass', 'fail')`<br />`expect({ pass: 1, fail: 2 }).to.have.keys('pass', 'fail')`                                                                                                                |
| throw(_constructor_) <br /><small>**Aliases:** throws, Throw</small>                      | `.should('throw', Error)`<br />`expect(fn).to.throw(Error)`                                                                                                                                                            |
| respondTo(_method_) <br /><small>**Aliases:** respondsTo</small>                          | `.should('respondTo', 'getName')`<br />`expect(obj).to.respondTo('getName')`                                                                                                                                           |
| itself                                                                                    | `.should('itself.respondTo', 'getName')`<br />`expect(Foo).itself.to.respondTo('bar')`                                                                                                                                 |
| satisfy(_method_) <br /><small>**Aliases:** satisfies</small>                             | `.should('satisfy', (num) => num > 0)`<br />`expect(1).to.satisfy((num) => num > 0)`                                                                                                                                   |
| closeTo(_expected_, _delta_) <br /><small>**Aliases:** approximately</small>              | `.should('be.closeTo', 1, 0.5)`<br />`expect(1.5).to.be.closeTo(1, 0.5)`                                                                                                                                               |
| members(_set_)                                                                            | `.should('include.members', [3, 2])`<br />`expect([1, 2, 3]).to.include.members([3, 2])`                                                                                                                               |
| oneOf(_values_)                                                                           | `.should('be.oneOf', [1, 2, 3])`<br />`expect(2).to.be.oneOf([1,2,3])`                                                                                                                                                 |
| change(_function_) <br /><small>**Aliases:** changes</small>                              | `.should('change', obj, 'val')`<br />`expect(fn).to.change(obj, 'val')`                                                                                                                                                |
| increase(_function_) <br /><small>**Aliases:** increases</small>                          | `.should('increase', obj, 'val')`<br />`expect(fn).to.increase(obj, 'val')`                                                                                                                                            |
| decrease(_function_) <br /><small>**Aliases:** decreases</small>                          | `.should('decrease', obj, 'val')`<br />`expect(fn).to.decrease(obj, 'val')`                                                                                                                                            |

These getters are also available for BDD assertions. They don't actually do
anything, but they enable you to write clear, English sentences.

| Chainable getters                                                                           |
| ------------------------------------------------------------------------------------------- |
| `to`, `be`, `been`, `is`, `that`, `which`, `and`, `has`, `have`, `with`, `at`, `of`, `same` |

## Chai-jQuery

<Icon name="github" url="https://github.com/chaijs/chai-jquery" />

These chainers are available when asserting about a DOM object.

You will commonly use these chainers after using DOM commands like:
[`cy.get()`](/api/commands/get), [`cy.contains()`](/api/commands/contains), etc.

{/* textlint-disable */}

| Chainers                | Assertion                                                                                                                    |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| attr(_name_, _[value]_) | `.should('have.attr', 'bar')`<br />`expect($el).to.have.attr('foo', 'bar')`                                                  |
| prop(_name_, _[value]_) | `.should('have.prop', 'disabled', false)`<br />`expect($el).to.have.prop('disabled', false)`                                 |
| css(_name_, _[value]_)  | `.should('have.css', 'background-color', 'rgb(0, 0, 0)')`<br />`expect($el).to.have.css('background-color', 'rgb(0, 0, 0)')` |
| data(_name_, _[value]_) | `.should('have.data', 'foo', 'bar')`<br />`expect($el).to.have.data('foo', 'bar')`                                           |
| class(_className_)      | `.should('have.class', 'foo')`<br />`expect($el).to.have.class('foo')`                                                       |
| id(_id_)                | `.should('have.id', 'foo')`<br />`expect($el).to.have.id('foo')`                                                             |
| html(_html_)            | `.should('have.html', 'I love testing')`<br />`expect($el).to.have.html('with Cypress')`                                     |
| text(_text_)            | `.should('have.text', 'I love testing')`<br />`expect($el).to.have.text('with Cypress')`                                     |
| value(_value_)          | `.should('have.value', 'test@dev.com')`<br />`expect($el).to.have.value('test@dev.com')`                                     |
| visible                 | `.should('be.visible')`<br />`expect($el).to.be.visible`                                                                     |
| hidden                  | `.should('be.hidden')`<br />`expect($el).to.be.hidden`                                                                       |
| selected                | `.should('be.selected')`<br />`expect($option).not.to.be.selected`                                                           |
| checked                 | `.should('be.checked')`<br />`expect($input).not.to.be.checked`                                                              |
| focus[ed]               | `.should('have.focus')`<br />`expect($input).not.to.be.focused`<br />`expect($input).to.have.focus`                          |
| enabled                 | `.should('be.enabled')`<br />`expect($input).to.be.enabled`                                                                  |
| disabled                | `.should('be.disabled')`<br />`expect($input).to.be.disabled`                                                                |
| empty                   | `.should('be.empty')`<br />`expect($el).not.to.be.empty`                                                                     |
| exist                   | `.should('exist')`<br />`expect($nonexistent).not.to.exist`                                                                  |
| match(_selector_)       | `.should('match', ':empty')`<br />`expect($emptyEl).to.match(':empty')`                                                      |
| contain(_text_)         | `.should('contain', 'text')`<br />`expect($el).to.contain('text')`                                                           |
| descendants(_selector_) | `.should('have.descendants', 'div')`<br />`expect($el).to.have.descendants('div')`                                           |

{/* textlint-enable */}

## Sinon-Chai

<Icon name="github" url="https://github.com/domenic/sinon-chai" />

These chainers are used on assertions with [`cy.stub()`](/api/commands/stub) and
[`cy.spy()`](/api/commands/spy).

| Sinon.JS property/method | Assertion                                                                                                                 |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
| called                   | `.should('have.been.called')`<br />`expect(spy).to.be.called`                                                             |
| callCount                | `.should('have.callCount', 3)`<br />`expect(spy).to.have.callCount(n)`                                                    |
| calledOnce               | `.should('have.been.calledOnce')`<br />`expect(spy).to.be.calledOnce`                                                     |
| calledTwice              | `.should('have.been.calledTwice')`<br />`expect(spy).to.be.calledTwice`                                                   |
| calledThrice             | `.should('have.been.calledThrice')`<br />`expect(spy).to.be.calledThrice`                                                 |
| calledBefore             | `.should('have.been.calledBefore', spy2)`<br />`expect(spy1).to.be.calledBefore(spy2)`                                    |
| calledAfter              | `.should('have.been.calledAfter', spy2)`<br />`expect(spy1).to.be.calledAfter(spy2)`                                      |
| calledWithNew            | `.should('have.been.calledWithNew')`<br />`expect(spy).to.be.calledWithNew`                                               |
| alwaysCalledWithNew      | `.should('have.always.been.calledWithNew')`<br />`expect(spy).to.always.be.calledWithNew`                                 |
| calledOn                 | `.should('have.been.calledOn', context)`<br />`expect(spy).to.be.calledOn(context)`                                       |
| alwaysCalledOn           | `.should('have.always.been.calledOn', context)`<br />`expect(spy).to.always.be.calledOn(context)`                         |
| calledWith               | `.should('have.been.calledWith', ...args)`<br />`expect(spy).to.be.calledWith(...args)`                                   |
| alwaysCalledWith         | `.should('have.always.been.calledWith', ...args)`<br />`expect(spy).to.always.be.calledWith(...args)`                     |
| calledOnceWith           | `.should('have.been.calledOnceWith', ...args)`<br />`expect(spy).to.be.calledOnceWith(...args)`                           |
| calledWithExactly        | `.should('have.been.calledWithExactly', ...args)`<br />`expect(spy).to.be.calledWithExactly(...args)`                     |
| alwaysCalledWithExactly  | `.should('have.always.been.calledWithExactly', ...args)`<br />`expect(spy).to.always.be.calledWithExactly(...args)`       |
| calledOnceWithExactly    | `.should('have.been.calledOnceWithExactly', ...args)`<br />`expect(spy).to.be.calledOnceWithExactly(...args)`             |
| calledWithMatch          | `.should('have.been.calledWithMatch',...args)`<br />`expect(spy).to.be.calledWithMatch(...args)`                          |
| alwaysCalledWithMatch    | `.should('have.always.been.calledWithMatch',...args)`<br />`expect(spy).to.always.be.calledWithMatch(...args)`            |
| returned                 | `.should('have.returned', 'foo')`<br />`expect(spy).to.have.returned(returnVal)`                                          |
| alwaysReturned           | `.should('have.always.returned', 'foo')`<br />`expect(spy).to.have.always.returned(returnVal)`                            |
| threw                    | `.should('have.thrown', TypeError)`<br />`expect(spy).to.have.thrown(errorObjOrErrorTypeStringOrNothing)`                 |
| alwaysThrew              | `.should('have.always.thrown', 'TypeError')`<br />`expect(spy).to.have.always.thrown(errorObjOrErrorTypeStringOrNothing)` |

## Adding New Assertions

Because we are using `chai`, that means you can extend it however you'd like.
Cypress will "just work" with new assertions added to `chai`. You can:

- Write your own `chai` assertions as
  [documented here](https://chaijs.com/guide/helpers/).
- npm install any existing `chai` library and import into your test file or
  [support file](/app/core-concepts/writing-and-organizing-tests#Support-file).

:::info

[Check out our example recipe extending chai with new assertions.](/app/references/recipes#Fundamentals)

:::

## Common Assertions

Here is a list of common element assertions. Notice how we use these assertions
(listed above) with [`.should()`](/api/commands/should). You may also want to
read about how Cypress [retries](/app/core-concepts/retry-ability)
assertions.

### Length

```javascript
// retry until we find 3 matching <li.selected>
cy.get('li.selected').should('have.length', 3)
```

### Class

```javascript
// retry until this input does not have class disabled
cy.get('form').find('input').should('not.have.class', 'disabled')
```

### Value

```javascript
// retry until this textarea has the correct value
cy.get('textarea').should('have.value', 'foo bar baz')
```

### Text Content

```javascript
// assert the element's text content is exactly the given text
cy.get('[data-testid="user-name"]').should('have.text', 'Joe Smith')
// assert the element's text includes the given substring
cy.get('[data-testid="address"]').should('include.text', 'Atlanta')
// retry until this span does not contain 'click me'
cy.get('a').parent('span.help').should('not.contain', 'click me')
// the element's text should start with "Hello"
cy.get('[data-testid="greeting"]')
  .invoke('text')
  .should('match', /^Hello/)
// use cy.contains to find an element with its text
// matching the given regular expression
cy.contains('[data-testid="greeting"]', /^Hello/)
```

:::info

**Tip:** read about assertions against text with non-breaking space entities in
[How do I get an element's text contents?](/app/faq#How-do-I-get-an-elements-text-contents)

:::

### Visibility

```javascript
// retry until the element with
// data-testid "form-submit" is visible
cy.get('[data-testid="form-submit"]').should('be.visible')
// retry until the list item with
// text "write tests" is visible
cy.contains('[data-testid="todo"] li', 'write tests').should('be.visible')
```

**Note:** if there are multiple elements, the assertions `be.visible` and
`not.be.visible` act differently:

```javascript
// retry until SOME elements are visible
cy.get('li').should('be.visible')
// retry until EVERY element is invisible
cy.get('li.hidden').should('not.be.visible')
```

Watch the short video
["Multiple elements and should('be.visible') assertion"](https://www.youtube.com/watch?v=LxkrhUEE2Qk)
that shows how to correctly check the visibility of elements.

### Existence

```javascript
// retry until loading spinner no longer exists
cy.get('[data-testid="loading"]').should('not.exist')
```

### State

```javascript
// retry until our radio is checked
cy.get(':radio').should('be.checked')
```

### CSS

```javascript
// retry until element has matching css
cy.get('[data-testid="completed"]').should(
  'have.css',
  'text-decoration',
  'line-through'
)
```

```javascript
// retry while accordion css has the
// "display: none" property
cy.get('[data-testid="accordion"]').should('not.have.css', 'display', 'none')
```

### Disabled property

```html
<input type="text" data-testid="example-input" disabled />
```

```javascript
cy.get('[data-testid="example-input"]')
  .should('be.disabled')
  // let's enable this element from the test
  .invoke('prop', 'disabled', false)

cy.get('[data-testid="example-input"]')
  // we can use "enabled" assertion
  .should('be.enabled')
  // or negate the "disabled" assertion
  .and('not.be.disabled')
```

## Negative assertions

There are positive and negative assertions. Examples of positive assertions are:

```javascript
cy.get('[data-testid="todo-item"]')
  .should('have.length', 2)
  .and('have.class', 'completed')
```

The negative assertions have the "not" chainer prefixed to the assertion.
Examples of negative assertions are:

```javascript
cy.contains('first todo').should('not.have.class', 'completed')
cy.get('[data-testid="loading"]').should('not.be.visible')
```

### <Icon name="exclamation-triangle" color="red"/> False passing tests

Negative assertions may pass for reasons you weren't expecting. Let's say we
want to test that a Todo list app adds a new Todo item after typing the Todo and
pressing enter.

**Positive assertions**

When adding an element to the list and using a **positive assertion**, the test
asserts a specific number of Todo items in our application.

The test below may still falsely pass if the application behaves unexpectedly,
like adding a blank Todo, instead of adding the new Todo with the text "Write
tests".

```javascript
cy.get('[data-testid="todos"]').should('have.length', 2)
cy.get('[data-testid="new-todo"]').type('Write tests{enter}')

// using a positive assertion to check the
// exact number of items
cy.get('[data-testid="todos"]').should('have.length', 3)
```

**Negative assertions**

But when using a **negative assertion** in the test below, the test can falsely
pass when the application behaves in multiple unexpected ways:

- The app deletes the entire list of Todo items instead of inserting the 3rd
  Todo
- The app deletes a Todo instead of adding a new Todo
- The app adds a blank Todo

```javascript
cy.get('[data-testid="todos"]').should('have.length', 2)
cy.get('[data-testid="new-todo"]').type('Write tests{enter}')

// using negative assertion to check it's
// not a number of items
cy.get('[data-testid="todos"]').should('not.have.length', 2)
```

## Should callback

If built-in assertions are not enough, you can write your own assertion function
and pass it as a callback to the `.should()` command. Cypress will automatically
[retry](/app/core-concepts/retry-ability) the callback function until it
passes or the command times out. See the
[`.should()`](/api/commands/should#Function) documentation.

```html
<div class="main-abc123 heading-xyz987">Introduction</div>
```

```javascript
cy.get('div').should(($div) => {
  expect($div).to.have.length(1)

  const className = $div[0].className

  // className will be a string like "main-abc123 heading-xyz987"
  expect(className).to.match(/heading-/)
})
```

## Multiple assertions

You can attach multiple assertions to the same command.

```html
<a
  data-testid="assertions-link"
  class="active"
  href="https://on.cypress.io"
  target="_blank"
>
  Cypress Docs
</a>
```

```js
cy.get('[data-testid="assertions-link"]')
  .should('have.class', 'active')
  .and('have.attr', 'href')
  .and('include', 'cypress.io')
```

Note that all chained assertions will use the same reference to the original
subject. For example, if you wanted to test a loading element that first appears
and then disappears, the following WILL NOT WORK because the same element cannot
be visible and invisible at the same time:

```js
// ⛔️ DOES NOT WORK
cy.get('[data-testid="loading"]').should('be.visible').and('not.be.visible')
```

Instead you should split the assertions and re-query the element:

```js
// ✅ THE CORRECT WAY
cy.get('[data-testid="loading"]').should('be.visible')
cy.get('[data-testid="loading"]').should('not.be.visible')
```

## See also

- [Guide: Introduction to Cypress](/app/core-concepts/introduction-to-cypress#Assertions)
- [cypress-example-kitchensink Assertions](https://example.cypress.io/commands/assertions)
